--[[
    雪月框架    同步模块    v1.2

    新增    数据类型还原
            每个参数多花费一字节记录变量类型，解析数据包时再还原出来，方便直接调用

    依赖模块/函数特别说明
        string.split(str, s) 分割字符串

    雪月灬雪歌  2022/10/3  05:40
]]

local DzSyncData                = japi.DzSyncData
local DzTriggerRegisterSyncData = japi.DzTriggerRegisterSyncData
local DzGetTriggerSyncData      = japi.DzGetTriggerSyncData

---@class sync_data
local sync_data = {
    type = 'sync_data',
    __mode = 'k',
}
---数据格式化
local map_dataFormat = {
    number = function (value)
        --由于or 0 所以不存在nil情况
        local tp = math.type( tonumber(value or '0') or 0 )
        if tp == 'integer' then
            value = 'i' .. value
        else
            value =  'f' .. value
        end
        return value
    end,
    string = function (value)
        return 's' .. value
    end,
    boolean = function (value)
        return 'b' .. base.B2I( value )
    end,
    ['nil'] = function (value)
        return 'n'
    end,
}
---数据解析
local map_dataParser = {
    i = function (value)
        return math.floor( tonumber(value) )
    end,
    f = function (value)
        return tonumber(value) * 1.00
    end,
    s = function (value)
        return value
    end,
    b = function (value)
        return 'b' .. base.I2B( value )
    end,
    n = function (_)
        return nil
    end,

}

sync_data.__index = sync_data

local table_insert = table_insert
sync_data.__call = function(self)
    local data = {}
    local func
    table_insert( data,  self[1]  )
    for i = 2, #self, 1 do
        func = map_dataFormat[ type(self[i]) ]
        if func then
            table_insert( data, func( self[i] ) )
        end
    end

	return table.concat(data,"&")
end
--sync class
sync = setmetatable({},{
    type = 'class',
    class = 'sync',
})

local __callback = {}

--中心分发器传参用
local package         = setmetatable( {}, sync )
local SYNC_SYSTEM_TAG = 'XG_SYNC'

--生成同步数据包
---@param ... any 任意个数据，但注意 如果添加的是一张表，只会检索一层表
---@return sync_data 返回一个同步数据包
function sync:new(...)

    local t = setmetatable(
    {
        [1] = "", --默认同步标签占位
    },
    sync_data
    )

    t:Add(...)
    return t
end


---加载同步的数据包
---@alias dataType string|number|boolean|nil
---@return table<int,dataType>
function sync:load()
	return package
end


--注册同步回调[]
---@param tag string 回调标签
---@param func function 回调函数
function sync:callback(tag, func)
    if type(func) ~= 'function' then return end
    if not __callback [tag] then
        __callback [tag] = { [0] = 1, func }
    else
        local m = __callback [tag] [0]

        table.insert( __callback [tag] , func )
    end
    return func
end



--往同步数据包内添加数据
---@param self sync_data
---@param ... any 任意个数据，但注意 如果添加的是一张表，只会检索一层表
function sync_data:Add(...)
	local d = { ... }
	for i=1,#d do
		local p = type(d[i])
		if p == 'nil' then
		elseif p == 'string' then
			table.insert( self, d[i] )
		elseif p == 'table' then
			for j=1,#d[i] do
				table.insert( self, tostring(d[i][j]) )
			end
		else
			table.insert(self, d[i])
		end
	end
    --方便连续元方法
    return self
end

--self:sync_data
--发送同步数据包
--@param tag string 同步标签，你需要使用sync(class)注册一个同步回调
function sync_data:Send(tag)
    self[1] = tag
	DzSyncData( SYNC_SYSTEM_TAG, self( ) )
end

--@private
--模块中心分发器

local trg  = cj.CreateTrigger() --同步模块中心分发器
DzTriggerRegisterSyncData(trg, SYNC_SYSTEM_TAG, false)
local function action()

    --package可用于传参 回调中使用 sync:load() 可载入同步数据包
    package = ( DzGetTriggerSyncData() or '' ):split( "&" )

    local data = {}
    local func
    table_insert( data,  package[1] )
    for i = 2, #package, 1 do
        local tp = package[i]:sub(1,1)
        func = map_dataParser[ tp ]
        if func then
            table_insert( data, func( package[i]:sub(2) ) )
        end
    end
    package = data

    local tag = package [ 1 ] or ''
    table.remove(package, 1) --移除同步标签
    setmetatable( package, sync_data )

    for i,v in ipairs( __callback [tag] ) do
        v ( )
    end

end
cj.TriggerAddAction( trg, action )
